#ifndef __INK_TIME_H__
#define __INK_TIME_H__

#include <time.h>
#include <stdint.h>

/**
* 提供精确到纳秒级的时间操作函数
*/

typedef int64_t ink_hrtime;

#define HRTIME_HOUR 		(60 * HRTIME_MINUTE)
#define HRTIME_MINUTE 		(60 * HRTIME_SECOND)
#define HRTIME_SECOND		(1000 * HRTIME_MSECOND)
#define HRTIME_MSECOND		(1000 * HRTIME_USECOND)
#define HRTIME_USECOND		(1000 * HRTIME_NSECOND)
#define HRTIME_NSECOND		(1LL)


static inline ink_hrtime
ink_hrtime_from_hource(ink_hrtime hour)
{
	return (hour * HRTIME_HOUR);
}

static inline ink_hrtime
ink_hrtime_from_minute(ink_hrtime minute)
{
	return (minute * HRTIME_MINUTE);
}

static inline ink_hrtime
ink_hrtime_from_second(ink_hrtime second)
{
	return (second * HRTIME_SECOND);
}

static inline ink_hrtime
ink_hrtime_from_msecond(ink_hrtime msecond)
{
	return (msecond * HRTIME_MSECOND);
}

static inline ink_hrtime
ink_hrtime_from_usecond(ink_hrtime usecond)
{
	return (usecond * HRTIME_USECOND);
}

static inline ink_hrtime
ink_hrtime_from_nsecond(ink_hrtime nsecond)
{
	return (nsecond * HRTIME_NSECOND);
}

//the ink_hrtime is nsecond
static inline ink_hrtime
ink_hrtime_from_timespec(const struct timespec *ts)
{
	return ink_hrtime_from_second(ts->tv_sec) + ink_hrtime_from_nsecond(ts->tv_nsec);
}

//the ink_hrtime is nsecond
static inline ink_hrtime
ink_hrtime_from_timeval(const struct timeval *tv)
{
	return ink_hrtime_from_second(tv->tv_sec) + ink_hrtime_from_usecond(tv->tv_usec);
}

static inline ink_hrtime
ink_hrtime_to_hource(ink_hrtime t)
{
	return ((ink_hrtime)(t / HRTIME_HOUR));
}

static inline ink_hrtime
ink_hrtime_to_minute(ink_hrtime t)
{
	return ((ink_hrtime)(t / HRTIME_MINUTE));
}

static inline ink_hrtime
ink_hrtime_to_second(ink_hrtime t)
{
	return ((ink_hrtime)(t / HRTIME_SECOND));
}

static inline ink_hrtime
ink_hrtime_to_msecond(ink_hrtime t)
{
	return ((ink_hrtime)(t / HRTIME_MSECOND));
}

static inline ink_hrtime
ink_hrtime_to_usecond(ink_hrtime t)
{
	return ((ink_hrtime)(t / HRTIME_USECOND));
}

static inline ink_hrtime
ink_hrtime_to_nsecond(ink_hrtime t)
{
	return ((ink_hrtime)(t / HRTIME_NSECOND));
}

//the t is nsecond
static inline struct timespec
ink_hrtime_to_timespec(ink_hrtime t)
{
	struct timespec ts;
	ts.tv_sec = ink_hrtime_to_second(t);
	ts.tv_nsec = t % HRTIME_SECOND;
	return ts;
}

//the t is nsecond
static inline void
ink_hrtime_to_timespec2(ink_hrtime t, struct timespec *ts)
{
	ts->tv_sec = ink_hrtime_to_second(t);
	ts->tv_nsec = t % HRTIME_SECOND;
}

//the t is nsecond
static inline struct timeval
ink_hrtime_to_timeval(ink_hrtime t)
{
	int64_t usecs;
	struct timeval tv;
	usecs = ink_hrtime_to_usecond(t);
	tv.tv_sec = usecs / 1000000;
	tv.tv_usec = usecs % 1000000;
	return tv;
}

//the t is nsecond
static inline void
ink_hrtime_to_timeval2(ink_hrtime t, struct timeval *tv)
{
	int64_t usecs = ink_hrtime_to_usecond(t);
	tv->tv_sec = usecs / 1000000;
	tv->tv_usec = usecs / 1000000;
}

static inline ink_hrtime
ink_get_base_hrtime_internal()
{
	timespec ts;
	clock_gettime(CLOCK_REALTIME, &ts);
	return ink_hrtime_from_timespec(&ts);
}

static inline ink_hrtime
ink_time_second()
{
	return ink_hrtime_to_second(ink_get_base_hrtime_internal());
}

static inline ink_hrtime
ink_time_msecond()
{
	return ink_hrtime_to_msecond(ink_get_base_hrtime_internal());
}

static inline ink_hrtime
ink_time_usecond()
{
	return ink_hrtime_to_usecond(ink_get_base_hrtime_internal());
}

static inline ink_hrtime
ink_time_nsecond()
{
	return ink_hrtime_to_nsecond(ink_get_base_hrtime_internal());
}

#endif
